package com.gzkemays.server1.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.annotation.Resource;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  private static final String RESOURCE_ID = "resource-1";
  @Resource private RedisConnectionFactory redisConnectionFactory;

  /**
   * 添加特定于资源服务器的属性
   *
   * <p>添加了 tokenService 并且为 DefaultTokenService 在从 auth-server 获取 token 后，如果配置与 auth-server 相同的
   * token 存储仓库，那么当访问 service-1 api 的时候，校验 token 就不需要在 auth-server 进行校验。而是直接通过 service-1 的
   * tokenStore 进行处理
   *
   * <p>如果不加 tokenStore 那么将被 auth-server 的 OAuth2AuthenticationProcessingFilter 的 doFilter 进行拦截
   *
   * @param resources
   */
  @Override
  public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
    defaultTokenServices.setTokenStore(tokenStore());
    resources.resourceId(RESOURCE_ID).tokenServices(defaultTokenServices);
  }

  /**
   * 使用此配置安全资源的访问规则，配置需要token验证的url。 默认情况下，所有不在"/oauth/**"中的资源都受到保护。
   *
   * @param http
   * @throws Exception
   */
  @Override
  public void configure(HttpSecurity http) throws Exception {
    // /api/* 都需要token验证，会被 OAuth2AuthenticationProcessingFilter 处理
    http.requestMatchers()
        .antMatchers("/api/*")
        .and()
        .authorizeRequests()
        .anyRequest()
        .authenticated();
  }

  /**
   * 配置redis，使用redis存token
   *
   * @return
   */
  @Bean
  public TokenStore tokenStore() {
    return new RedisTokenStore(redisConnectionFactory);
  }
}
